package com.example.demo.config;

import com.example.demo.domain.SysLog;
import com.example.demo.service.SysLogService;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;

@Aspect
@Component
public class LogAsPect {
    
    private final static Logger log = org.slf4j.LoggerFactory.getLogger(LogAsPect.class);

    @Autowired@Lazy
    private SysLogService sysLogService;
    
    //表示匹配带有自定义注解的方法
//    @Pointcut("@annotation(com.example.demo.config.Log)")
//    public void pointcut() {}
//
    @Pointcut("execution(* com.example.demo.service.*.*(..))" )
    public void pointcut() {}

    @Pointcut("execution(* com.example.demo.controller.*.*(..))" )
    public void pointcut1() {}

    @Pointcut("execution(* com.example.demo.controller.TestController.*(..))" )
    public void pointcut2() {}


    @Around(value = "pointcut() || pointcut1()")
    public Object around(ProceedingJoinPoint point) {
        Object result =null;
        long beginTime = System.currentTimeMillis();
        
        try {
            log.info("我在目标方法之前执行！");
            result = point.proceed();
            long endTime = System.currentTimeMillis();
            insertLog(point,endTime-beginTime);
        } catch (Throwable e) {
            // TODO Auto-generated catch block
        }
        return result;
    }
    
    private void insertLog(ProceedingJoinPoint point ,long time) {
        MethodSignature signature = (MethodSignature)point.getSignature();
        Method method = signature.getMethod();
        SysLog sys_log = new SysLog();

//        ApiOperation apiOperation1 = method.getDeclaredAnnotation(ApiOperation.class);
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        Log userAction = method.getAnnotation(Log.class);
        if (userAction != null) {
            // 注解上的描述
            sys_log.setUserAction(apiOperation.value());
        }else {
            sys_log.setUserAction("这个方法没有@ApiOperation");
        }
        
        // 请求的类名
        String className = point.getTarget().getClass().getName();
        // 请求的方法名
        String methodName = signature.getName();
        // 请求的方法参数值
        String args = Arrays.toString(point.getArgs());
        
        //从session中获取当前登陆人id
//      Long useride = (Long)SecurityUtils.getSubject().getSession().getAttribute("userid");
        sys_log.setId(UUID.randomUUID().toString().substring(0,5));


        String userId = UUID.randomUUID().toString().substring(0,5);
        sys_log.setUserId(userId);
        
        sys_log.setCreateTime(new java.sql.Timestamp(System.currentTimeMillis()));
        
        log.info("当前登陆人：{},类名:{},方法名:{},参数：{},执行时间：{}",userId, className, methodName, args, time);
        
        sysLogService.save(sys_log);
    }


    @Before(value = "pointcut1()")
    public Object before(JoinPoint point) {
        Object result =null;

        MethodSignature methodSignature = (MethodSignature)point.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        String action = apiOperation.value();
        log.info("before");
        return result;
    }

    @After(value = "execution(* com.example.demo.controller.*.*(..))")
    public String afterAdvice(JoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String action = methodSignature.getMethod().getAnnotation(ApiOperation.class).value();
        log.warn("after:"+action);
        return null;
    }

    @AfterReturning(value = "execution(* com.example.demo.controller.*.*(..))")
    public void afterReturn(JoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        String action = apiOperation.value();
        log.warn("afterReturn:"+action);
    }

}